package org.NooLab.openNLP.grammar;

 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.NooLab.utilities.logging.PrintLog;



public class ConjugationHarvesterFactory {

	// the helper realized as callback
	HarvestersInitIntf pointOfInit;
	
	ArgumentsObject arguments = new ArgumentsObject() ;
	
	ConjugationHarvesterIntf  ConjHarvesterIntf ; 
	//VerbConjugationStorage verbConjugationStorage;
	
	String resourceAddr = "";
	String language ;
	
	String conjDataPath ;
	PrintLog out;
	
	
	
	public ConjugationHarvesterFactory(){
		
	}
	
	/**
	 * TODO: callback for instantiation
	 * 
	 * we could use reflection and ".instance()" to decouple even more... 
	 * that would be initiated by class LanguageProcessorCore{}, providing a reference to the class to use;
	 * LanguageProcessorCore{} would provide a callback function
	 * 
	 * without callback, we have no extensible architecture, any new provider has to be
	 * hard-coded here !
	 * 
	 * 
	 * @param lang
	 * @param conjdatapath
	 * @param verbconjugationstorage
	 * @param outprn
	 * @return
	 */
	public ConjugationHarvesterIntf getConjugationHarvester( String lang, 
										 					 String conjdatapath , 
										 					 VerbConjugationStorage verbconjugationstorage , 
										 					 PrintLog outprn ){
		
		ConjugationHarvesterIntf  cjh = null ; 
		
		
		language = lang;
		conjDataPath = conjdatapath ;
		
		// verbConjugationStorage = verbconjugationstorage ;
		out = outprn ;
		
		// instead of calling the constructors here, we should call a callback function, which is
		// provided by the originating instance itself
		// org.NooLab.openNLP.lang.de.LanguageProcessorGerman$initializationHost@1f8d244
		// pointofInit is instantiated in lang-spec LanguageProcessor, and it is called in their abstract super class
		// i.e. this callback calls back from here to the user of this harvester class
		cjh = pointOfInit.initConjHarvester( resourceAddr ) ;
		
		/* 
		if (resourceAddr.contains("reverso")){
			cjh = (ConjugationHarvesterIntf)(new ReversoConjugationHarvester( language, conjDataPath , verbConjugationStorage , out));
		}

		*/
		ConjHarvesterIntf = cjh;
		return cjh;
	} 
	
	
	public void setCallbackPoint( HarvestersInitIntf pointofinit ){
	
		pointOfInit = pointofinit ;
	}
	
	/**
	 * 
	 * even better, we would NOT supply the params here, but create the "intArgs[]" in the callback, and providing
	 * then just the intArgs
	 * 
	 * @param harvesterClass
	 * @param lang
	 * @param basepath
	 * @param pathext
	 * @param vc
	 * @param outprn
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
	public ConjugationHarvesterIntf getInstanceofHarvester( Class harvesterClass, Object[] intArgs ){
															// String lang,  String basepath, String pathext, VerbConjugationStorage vc, PrintLog outprn ){
		ConjugationHarvesterIntf  cjh = null;
		/*
		Class classDefinition = Class.forName(className);
        object = classDefinition.newInstance();
        */
		 
	    
	    // Class[] intArgsClass = new Class[] { String.class, String.class , String.class, VerbConjugationStorage.class, PrintLog.class };
	     
	    // Object[] intArgs = new Object[] { lang,  basepath, pathext, vc, outprn };
	    
	     
	    
	    Constructor intArgsConstructor;

	    try {
	    	
			arguments.setIntArgs(intArgs);

			intArgsConstructor = harvesterClass.getConstructor(arguments.getIntArgsClass());
			
			cjh = (ConjugationHarvesterIntf) createObject(intArgsConstructor,arguments.getIntArgs());

			// replacement for explicit construction:
			// cjh = (ConjugationHarvesterIntf)(new ReversoConjugationHarvester( language, basepath, pathext , verbConjugationStorage , out));
	      
	    } catch (NoSuchMethodException e) {
	      System.out.println(e);
	    }
	     
		return cjh;
	}
	
	 private Object createObject( Constructor constructor,  Object[] arguments) {

		// System.out.println("Constructor: " + constructor.toString());
		Object object = null;

		try {
			
			object = constructor.newInstance(arguments);
			
			// System.out.println("Object: " + object.toString());
			
			return object;
			
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
		return object;
	}
	// ------------------------------------------------------------------------
	
	public String getResourceAddr() {
		return resourceAddr;
	}

	public void setResourceAddr(String resourceAddr) {
		this.resourceAddr = resourceAddr;
	}

	public ArgumentsObject getArgumentsObject() {
		return arguments;
	}

	public void setArguments(ArgumentsObject arguments) {
		this.arguments = arguments;
	}
	
	
	
}
